package com.yq.skinlib.manage;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;

import androidx.annotation.AnyRes;
import androidx.annotation.Nullable;

import com.yq.skinlib.drawables.ColorStateListUtils;
import com.yq.skinlib.drawables.DrawableUtils;


public class SkinCompatResources {
    private static volatile SkinCompatResources sInstance;
    private Resources mResources;
    private String mSkinPkgName = "";
    private String mSkinName = "";
    private SkinCompatManager.SkinLoaderStrategy mStrategy;

    //添加颜色cache，不然每次都重新读取文件太卡了
    private SparseArray<ColorStateList> mCacheTintList;
    /**
     * 仅用于区分是否是自带官方红皮肤
     */
    private boolean isDefaultSkin = true;

    public static SkinCompatResources getInstance() {
        if (sInstance == null) {
            synchronized (SkinCompatResources.class) {
                if (sInstance == null) {
                    sInstance = new SkinCompatResources();
                }
            }
        }
        return sInstance;
    }


    /**
     * 加载皮肤失败是，恢复至之前的皮肤
     */
    public void reset() {
        reset(SkinCompatManager.getInstance().getStrategies().get(SkinCompatManager.SKIN_LOADER_STRATEGY_NONE));
    }

    public void reset(SkinCompatManager.SkinLoaderStrategy strategy) {
        mResources = SkinCompatManager.getInstance().getContext().getResources();
        mSkinPkgName = "";
        mSkinName = "";
        mStrategy = strategy;
        isDefaultSkin = true;
    }

    public void setupSkin(Resources resources, String pkgName, String skinName, SkinCompatManager.SkinLoaderStrategy
            strategy) {
        if (resources == null || TextUtils.isEmpty(pkgName) || TextUtils.isEmpty(skinName)) {
            reset(strategy);
            return;
        }
        mResources = resources;
        mSkinPkgName = pkgName;
        mSkinName = skinName;
        mStrategy = strategy;
        isDefaultSkin = skinName.equals("red");
        clear();
    }

    public Resources getSkinResources() {
        return mResources == null ? SkinCompatManager.getInstance().getContext().getResources() : mResources;
    }

    public String getSkinPkgName() {
        return mSkinPkgName;
    }

    @Deprecated
    public int getColor(int resId) {
        return getColor(SkinCompatManager.getInstance().getContext(), resId);
    }

    @Deprecated
    public Drawable getDrawable(int resId) {
        return getDrawable(SkinCompatManager.getInstance().getContext(), resId);
    }

    @Deprecated
    public ColorStateList getColorStateList(int resId) {
        return getColorStateList(SkinCompatManager.getInstance().getContext(), resId);
    }

    private int getTargetResId(Context context, int resId) {
        try {
            String resName = null;
            if (mStrategy != null) {
                resName = mStrategy.getTargetResourceEntryName(context, mSkinName, resId);
            }
            if (TextUtils.isEmpty(resName)) {
                resName = context.getResources().getResourceEntryName(resId);
            }
            String type = context.getResources().getResourceTypeName(resId);
            return getSkinResources().getIdentifier(resName, type, mSkinPkgName);
        } catch (Exception e) {
            // 换肤失败不至于应用崩溃.
            return 0;
        }
    }

    private int getSkinColor(Context context, int resId) {
        if (mStrategy != null) {
            ColorStateList colorStateList = mStrategy.getColor(context, mSkinName, resId);
            if (colorStateList != null) {
                if (SkinCompatManager.getInstance().isUseFilter()) {
                    return DrawableUtils.tintColor(colorStateList.getDefaultColor());
                }
                return colorStateList.getDefaultColor();
            }
        }
        if (!isDefaultSkin) {
            int targetResId = getTargetResId(context, resId);
            if (targetResId != 0) {
                if (SkinCompatManager.getInstance().isUseFilter()) {
                    return DrawableUtils.tintColor(getSkinResources().getColor(targetResId));
                }
                return getSkinResources().getColor(targetResId);
            }
        }
        if (SkinCompatManager.getInstance().isUseFilter()) {
            return DrawableUtils.tintColor(context.getResources().getColor(resId));
        }
        return context.getResources().getColor(resId);
    }

    @Nullable
    private ColorStateList getSkinColorStateList(Context context, int resId) {

        if (resId == 0) {
            return null;
        }

        ColorStateList colorStateList = mCacheTintList != null ? mCacheTintList.get(resId) : null;
        if (colorStateList == null) {
            if (mStrategy != null) {
                colorStateList = mStrategy.getColorStateList(context, mSkinName, resId);
            }

            if (colorStateList == null) {
                if (!isDefaultSkin) {
                    int targetResId = getTargetResId(context, resId);
                    if (targetResId != 0) {
                        colorStateList = ColorStateListUtils.createColorStateList(context, targetResId);
                    }
                }
            }

            if (colorStateList == null) {
                colorStateList = ColorStateListUtils.createColorStateList(context, resId);
            }

            if (colorStateList == null) {
                colorStateList = context.getResources().getColorStateList(resId);
            }

            if (colorStateList != null) {
                if (mCacheTintList == null) {
                    mCacheTintList = new SparseArray<>();
                }
                mCacheTintList.append(resId, colorStateList);
            }
        }

        return colorStateList;
    }

    @Nullable
    private Drawable getSkinDrawable(Context context, int resId) {
        if (resId == 0) {
            return null;
        }

        Drawable drawable = null;

        if (mStrategy != null) {
            drawable = mStrategy.getDrawable(context, mSkinName, resId);
            if (drawable != null) {
                return drawable;
            }
        }
        if (!isDefaultSkin) {
            int targetResId = getTargetResId(context, resId);
            if (targetResId != 0) {
                drawable = DrawableUtils.createDrawable(context, targetResId);
                if (drawable == null) {
                    drawable = getSkinResources().getDrawable(targetResId);
                }
            }
        }

        if (drawable == null) {
            drawable = DrawableUtils.createDrawable(context, resId);
        }
        //drawable为null，可能是图片资源直接获取
        if (drawable == null) {
            drawable = getSkinResources().getDrawable(resId);
        }
        return drawable;
    }

    private XmlResourceParser getSkinXml(Context context, int resId) {
        if (!isDefaultSkin) {
            int targetResId = getTargetResId(context, resId);
            if (targetResId != 0) {
                return getSkinResources().getXml(targetResId);
            }
        }
        return context.getResources().getXml(resId);
    }

    private void getSkinValue(Context context, @AnyRes int resId, TypedValue outValue, boolean resolveRefs) {
        if (!isDefaultSkin) {
            int targetResId = getTargetResId(context, resId);
            if (targetResId != 0) {
                getSkinResources().getValue(targetResId, outValue, resolveRefs);
                return;
            }
        }
        context.getResources().getValue(resId, outValue, resolveRefs);
    }

    public static int getColor(Context context, int resId) {
        return getInstance().getSkinColor(context, resId);
    }

    @Nullable
    public static ColorStateList getColorStateList(Context context, int resId) {
        return getInstance().getSkinColorStateList(context, resId);
    }

    @Nullable
    public static Drawable getDrawable(Context context, int resId) {
        return getInstance().getSkinDrawable(context, resId);
    }

    public static XmlResourceParser getXml(Context context, int resId) {
        return getInstance().getSkinXml(context, resId);
    }

    public static void getValue(Context context, @AnyRes int resId, TypedValue outValue, boolean resolveRefs) {
        getInstance().getSkinValue(context, resId, outValue, resolveRefs);
    }

    public Drawable getAttrDrawable(Context context, AttributeSet attrs, int attr) {
        final TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{attr});
        final int resId = a.getResourceId(0, 0);
        Drawable drawable = null;

        if (resId != 0) {
            if (mStrategy != null) {
                drawable = mStrategy.getDrawable(context, mSkinName, resId);
                if (drawable != null) {
                    return drawable;
                }
            }

            if (!isDefaultSkin) {
                int targetResId = getTargetResId(context, resId);
                if (targetResId != 0) {
                    drawable = DrawableUtils.createDrawable(context, targetResId);
                } else {
                    drawable = DrawableUtils.createDrawable(context, resId);
                }
            }

            if (drawable == null) {
                drawable = a.getDrawable(0);
            }
        }
        a.recycle();
        return drawable;
    }

    private TypedArray obtainAttributes(Resources res, Resources.Theme theme, AttributeSet set, int[] attrs) {
        if (theme == null) {
            return res.obtainAttributes(set, attrs);
        }
        return theme.obtainStyledAttributes(set, attrs, 0, 0);
    }

    public void clear() {
        if (mCacheTintList != null) {
            mCacheTintList.clear();
        }
    }
}
